import os
import sys
import threading
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.views import APIView
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from django.db.models import Q
from .models import Suite, RunResult
from .serializers import SuiteSerializer, RunResultSerializer
from case_api.models import Case

# 导入PyAllure API
sys.path.append(os.path.join(settings.BASE_DIR, 'PyAllure'))
from PyAllure.api import PyAllureAPI


class SuitePagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'size' 
    max_page_size = 100
    
    def get_paginated_response(self, data):
        return Response({
            'status': 200,
            'data': {
                'results': data,
                'count': self.page.paginator.count,  
                'next': self.get_next_link(),
                'previous': self.get_previous_link()
            }
        })


class SuiteViewSet(viewsets.ModelViewSet):
    queryset = Suite.objects.all()
    serializer_class = SuiteSerializer
    pagination_class = SuitePagination
    
    def get_queryset(self):
        """可以按项目ID过滤测试套件，支持搜索"""
        queryset = Suite.objects.all()
        
        # 按项目ID过滤
        project_id = self.request.query_params.get('project_id')
        if project_id:
            queryset = queryset.filter(project_id=project_id)
        
        # 按名称搜索
        name = self.request.query_params.get('name')
        if name:
            queryset = queryset.filter(name__icontains=name)
        
        # 按状态过滤
        status = self.request.query_params.get('status')
        if status:
            queryset = queryset.filter(status=status)
            
        return queryset.order_by('-created_time')
    
    def list(self, request, *args, **kwargs):
        """获取套件列表"""
        queryset = self.filter_queryset(self.get_queryset())  
        page = self.paginate_queryset(queryset)
        
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = self.get_serializer(queryset, many=True)
        return Response({
            'status': 200,
            'data': {
                'results': serializer.data,
                'count': len(serializer.data)
            }
        })
    
    def create(self, request, *args, **kwargs):
        """创建套件"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        
        return Response({
            'status': 201,
            'data': serializer.data,
            'msg': '套件创建成功'
        }, status=status.HTTP_201_CREATED)
    
    def update(self, request, *args, **kwargs):
        """更新套件"""
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        
        return Response({
            'status': 200,
            'data': serializer.data,
            'msg': '套件更新成功'
        })
    
    def destroy(self, request, *args, **kwargs):
        """删除套件"""
        instance = self.get_object()
        suite_name = instance.name
        self.perform_destroy(instance)
        
        return Response({
            'status': 200,
            'msg': f'套件"{suite_name}"删除成功'
        }, status=status.HTTP_200_OK)
    
    @action(detail=True, methods=['post'])
    def execute(self, request, pk=None):
        """执行测试套件
        
        URL: /api/suites/{id}/execute/
        请求体参数:
        {
            "suite_id": 1,  # 可选，默认使用URL中的ID
            "execution_time": "2024-01-01T00:00:00Z"  # 可选执行时间
        }
        """
        suite_id = pk or request.data.get('suite_id')
        if not suite_id:
            return Response({"error": "必须提供suite_id"}, status=status.HTTP_400_BAD_REQUEST)
            
        try:
            suite = Suite.objects.get(id=suite_id)
        except Suite.DoesNotExist:
            return Response({"error": "测试套件不存在"}, status=status.HTTP_404_NOT_FOUND)
        
        try:
            # 导入PyAllure API
            from PyAllure.api import PyAllureAPI
            from .models import SuiteExecutionRecord
            
            # 创建执行记录，初始为running
            record = SuiteExecutionRecord.objects.create(suite=suite, status='running')
            
            # 清理旧的测试用例文件
            PyAllureAPI.clean_testcases_dir()
            
            # 获取套件中的所有测试用例
            cases = suite.case_api_list.all()
            if not cases.exists():
                record.status = 'failed'
                record.result = '测试套件中没有测试用例'
                record.save()
                return Response({"error": "测试套件中没有测试用例"}, status=status.HTTP_400_BAD_REQUEST)
            
            # 转换用例格式并创建YAML文件
            for case in cases:
                case_data = PyAllureAPI.convert_django_case(case)
                file_name = f"test_{case.id}_{case.name}.yaml"
                PyAllureAPI.create_test_yaml(case_data, file_name)
            
            # 执行测试
            result = PyAllureAPI.run_tests()
            
            # 返回执行结果
            success = (result == 0)  # pytest.main 返回0表示成功
            record.status = 'success' if success else 'failed'
            record.result = f'测试套件"{suite.name}"执行成功' if success else f'测试套件"{suite.name}"执行失败'
            record.report_url = '/reports/index.html'
            record.executed_cases = cases.count()
            record.save()
            
            return Response({
                'success': success,
                'message': record.result,
                'report_url': record.report_url,
                'executed_cases': record.executed_cases,
                'execution': {
                    'status': record.status,
                    'result': record.result,
                    'report_url': record.report_url,
                    'executed_cases': record.executed_cases,
                    'created_at': record.created_at,
                }
            })
            
        except Exception as e:
            import traceback
            record.status = 'failed'
            record.result = str(e)
            record.save()
            print(traceback.format_exc())
            return Response({
                'success': False,
                'message': '测试执行出错',
                'error': str(e),
                'execution': {
                    'status': record.status,
                    'result': record.result,
                    'created_at': record.created_at,
                }
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def add_cases(self, request, pk=None):
        """向测试套件添加测试用例"""
        suite = self.get_object()
        case_ids = request.data.get('case_ids', [])
        
        if not case_ids:
            return Response({"error": "必须提供case_ids"}, status=status.HTTP_400_BAD_REQUEST)
        
        cases = Case.objects.filter(id__in=case_ids)
        for case in cases:
            suite.case_api_list.add(case)
        
        return Response({"message": f"成功添加 {len(cases)} 个测试用例"})
    
    @action(detail=True, methods=['post'])
    def remove_cases(self, request, pk=None):
        """从测试套件移除测试用例"""
        suite = self.get_object()
        case_ids = request.data.get('case_ids', [])
        
        if not case_ids:
            return Response({"error": "必须提供case_ids"}, status=status.HTTP_400_BAD_REQUEST)
        
        cases = Case.objects.filter(id__in=case_ids)
        for case in cases:
            suite.case_api_list.remove(case)
        
        return Response({"message": f"成功移除 {len(cases)} 个测试用例"})


class RunResultViewSet(viewsets.ModelViewSet):
    queryset = RunResult.objects.all()
    serializer_class = RunResultSerializer
    
    def get_queryset(self):
        """可以按项目ID或套件ID过滤执行结果"""
        queryset = RunResult.objects.all()
        project_id = self.request.query_params.get('project_id')
        suite_id = self.request.query_params.get('suite_id')
        
        if project_id:
            queryset = queryset.filter(project_id=project_id)
        if suite_id:
            queryset = queryset.filter(suite_id=suite_id)
            
        return queryset


class ExecuteTestView(APIView):
    """
    执行测试用例/测试套件
    """
    def post(self, request):
        suite_id = request.data.get('suite_id')
        case_ids = request.data.get('case_ids', [])
        
        if not suite_id and not case_ids:
            return Response({"error": "必须提供suite_id或case_ids"}, status=status.HTTP_400_BAD_REQUEST)
        
        # 获取要执行的用例
        if suite_id:
            try:
                suite = Suite.objects.get(id=suite_id)
                cases = suite.case_api_list.all()
                project = suite.project
            except Suite.DoesNotExist:
                return Response({"error": "测试套件不存在"}, status=status.HTTP_404_NOT_FOUND)
        else:
            cases = Case.objects.filter(id__in=case_ids)
            if not cases:
                return Response({"error": "未找到有效的测试用例"}, status=status.HTTP_404_NOT_FOUND)
            project = cases.first().project
            suite = None
        
        # 创建执行记录
        run_result = RunResult.objects.create(
            suite=suite,
            project=project,
            path="",
            status=1  # 准备开始
        )
        
        # 启动后台线程执行测试
        thread = threading.Thread(
            target=self._execute_test,
            args=(cases, run_result)
        )
        thread.daemon = True
        thread.start()
        
        return Response({
            "run_id": run_result.id,
            "status": "started",
            "message": "测试执行已启动",
            "check_url": f"/api/suite/reports/{run_result.id}/"
        })
    
    def _execute_test(self, cases, run_result):
        """后台执行测试"""
        try:
            # 更新状态为执行中
            run_result.status = 2
            run_result.save()
            
            # 导入PyAllure API
            from PyAllure.api import PyAllureAPI
            
            # 清理旧的测试用例文件
            PyAllureAPI.clean_testcases_dir()
            
            # 为每个用例创建YAML文件
            for case in cases:
                case_data = PyAllureAPI.convert_django_case(case)
                file_name = f"test_{case.id}_{case.name}.yaml"
                PyAllureAPI.create_test_yaml(case_data, file_name)
            
            # 执行测试
            result = PyAllureAPI.run_tests()
            
            # 更新执行结果
            run_result.status = 4  # 执行完毕
            run_result.is_pass = (result == 0)  # pytest.main 返回0表示成功
            run_result.save()
            
        except Exception as e:
            run_result.status = 5  # 执行出错
            run_result.save()
            import traceback
            print(traceback.format_exc())


class TestReportView(APIView):
    """
    获取测试报告
    """
    def get(self, request, run_id):
        try:
            run_result = RunResult.objects.get(id=run_id)
        except RunResult.DoesNotExist:
            return Response({"error": "执行记录不存在"}, status=status.HTTP_404_NOT_FOUND)
        
        # 获取报告路径 - 使用temps目录，因为allure-pytest生成的数据在这里
        pyallure_dir = os.path.join(settings.BASE_DIR, 'PyAllure')
        temp_dir = os.path.join(pyallure_dir, 'temps')
        
        # 读取测试结果数据
        test_results = []
        if os.path.exists(temp_dir):
            # 读取所有result.json文件
            for file in os.listdir(temp_dir):
                if file.endswith('-result.json'):
                    try:
                        with open(os.path.join(temp_dir, file), 'r', encoding='utf-8') as f:
                            import json
                            result_data = json.load(f)
                            test_results.append({
                                'name': result_data.get('name', '未命名测试'),
                                'status': result_data.get('status', 'unknown'),
                                'start': result_data.get('start', 0),
                                'stop': result_data.get('stop', 0),
                                'duration': result_data.get('stop', 0) - result_data.get('start', 0)
                            })
                    except:
                        pass
        
        # 计算测试结果统计
        total = len(test_results)
        passed = sum(1 for r in test_results if r['status'] == 'passed')
        failed = sum(1 for r in test_results if r['status'] == 'failed')
        skipped = sum(1 for r in test_results if r['status'] == 'skipped')
        
        summary = {
            'total': total,
            'passed': passed,
            'failed': failed,
            'skipped': skipped,
            'pass_rate': round(passed / total * 100, 2) if total > 0 else 0
        }
        
        # 构建报告URL - 可以通过Django的静态文件服务来访问
        report_url = f"/reports/index.html"
        
        return Response({
            "run_id": run_id,
            "status": run_result.status,
            "status_display": run_result.get_status_display(),
            "is_pass": run_result.is_pass,
            "report_url": report_url,
            "summary": summary,
            "test_results": test_results[:10]  # 只返回前10个结果
        })
